/**
 * 
 */
package it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.sheetbuilder;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;

import javax.imageio.ImageIO;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.Sprite;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.UniqueSpriteSheet;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.SpriteSheetCache;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.key.AbstractSheetKey;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.key.AvatarFrameKey;
import it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.key.PawnSheetKey;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.exceptions.InvalidFileException;

/**
 * @author Massimo Canonaco
 *
 */
public class PawnJSONLoader extends SpriteSheetBuilder {

	/* (non-Javadoc)
	 * @see it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.sheetbuilder.SpriteSheetBuilder#build(boolean, java.lang.String, java.lang.String, it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.key.AbstractSheetKey)
	 */
	@Override
	public void build(boolean light, String pathFolder, String file,AbstractSheetKey sheetKey, SpriteSheetCache cache) throws InvalidFileException 
	{
		JSONParser parser = new JSONParser();
		Object result = null;
		try 
		{
//			result = parser.parse(new FileReader(pathFolder+File.separator+file));
			result = parser.parse(new FileReader(pathFolder+file));
			if(light)
				produce(pathFolder, file, sheetKey, cache, result);
			else
			{
				// Setting key for the "AVATAR" part
				PawnSheetKey psk = new PawnSheetKey();
				psk.setWho(((PawnSheetKey)sheetKey).getWho());
				psk.setWhat(PawnSheetKey.FRAME_TYPE_ANIMATIONS);
				produce(pathFolder, file, psk, cache, result);
				
				// Setting key for the "ISOMETRIC MATCH" part
				psk.setWho(((PawnSheetKey)sheetKey).getWho());
				psk.setWhat(PawnSheetKey.FRAME_TYPE_AVATAR);
				psk.setWhen("");
				produce(pathFolder, file, psk, cache, result);
			}
		} catch (IOException | ParseException e) 
		{
			e.printStackTrace();
			System.exit(0);
//			throw new InvalidFileException();
		}
	}

	/* (non-Javadoc)
	 * @see it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.sheetbuilder.SpriteSheetBuilder#lightBuild(java.lang.String, java.lang.String, it.unical.canonaco.rende.igpe.game.cbv.guilayer.sprites.key.AbstractSheetKey)
	 */
	@Override
	protected void produce(String pathFolder, String file, AbstractSheetKey sheetKey, SpriteSheetCache cache, Object result) throws FileNotFoundException, IOException{
				
		if(sheetKey instanceof PawnSheetKey)
		{
			UniqueSpriteSheet resultSheet = null;
			
			PawnSheetKey psk = (PawnSheetKey) sheetKey.getCopy();
				final String KEY = "key";
				JSONObject jsonResult = (JSONObject) result;

				psk.setWho((String) jsonResult.get(KEY));
				
				// Check what 'type' of building is requested
				if(psk.getWhat().equals(PawnSheetKey.FRAME_TYPE_AVATAR))
				{
//					System.out.println("AVATAR BUILD");
					final String FILES = "files", 
							PRE_PLAY_MATCH = "ppm",
							INFORMATIONS = "informations";
					String imageFile = (String) ((JSONObject) jsonResult.get(FILES)).get(PRE_PLAY_MATCH);
					resultSheet = this.buildAvatarSprites(jsonResult, psk, (JSONObject) jsonResult.get(INFORMATIONS));
					resultSheet.setImage(ImageIO.read(new FileInputStream(pathFolder+File.separator+imageFile)));
//					System.out.println(pathFolder+File.separator+imageFile);
					cache.add(psk, resultSheet);
				}
				else
				{
//					System.out.println("MOTION BUILD");
					this.buildMotionsSprites(jsonResult, psk, pathFolder, cache);
				}
		}
	}
	
	/**
	 * @throws IOException 
	 * @throws FileNotFoundException  */
	private void buildMotionsSprites(JSONObject jsonResult, PawnSheetKey psk, final String pathFolder, SpriteSheetCache cache) throws FileNotFoundException, IOException
	{
//		try
//		{
			final String FILES = "files", 
					MOTIONS = "motions",
					ANIMATIONS = "animations",
					ISOTILE = "isotile",
					WIDTH = "width", HEIGHT = "height",
					ROW = "row", NAME = "name", MAXFRAME = "max_frame";
			
			JSONObject trickyTemp = (JSONObject) ((JSONObject) jsonResult.get(MOTIONS)).get(ISOTILE);
			
			long isoTileWidth = (long) trickyTemp.get(WIDTH), 
					isoTileHeight = (long) trickyTemp.get(HEIGHT);

			LinkedList<Sprite> motionsSprite = new LinkedList<>();
			JSONArray array = (JSONArray) ((JSONObject) jsonResult.get(MOTIONS)).get(ANIMATIONS);
			int arraySize = array.size();

			long maxFrame = -1, row = -1, secondToLast = 0;
			int frameRow = -1;
			String frameName = null;
			Sprite previous = null, actual = null;

			for(int index = 0; index < arraySize; index++)
			{
				trickyTemp = (JSONObject)array.get(index);
				maxFrame = (long) trickyTemp.get(MAXFRAME);
				secondToLast = maxFrame -1;
				row = (long)trickyTemp.get(ROW);
				frameRow = (int)(row*isoTileHeight);
				frameName = (String)trickyTemp.get(NAME);
				for(int frameIndex = 0; frameIndex < maxFrame; frameIndex++)
				{
					if(frameIndex > 0 && index < secondToLast)
					{
						previous = actual;
					}

					actual = new Sprite();

					if(previous != null)
					{
						previous.setNext(actual);
					}

					actual.setHeight((int)isoTileHeight);
					actual.setWidth((int)isoTileWidth);
//					actual.setTopX(frameRow);
//					actual.setTopY((int)(frameIndex*isoTileWidth));
					actual.setTopX((int)(frameIndex*isoTileWidth));
					actual.setTopY(frameRow);
					actual.setFrameName(frameName+frameIndex);
//					System.out.println("nome : "+actual.getFrameName()+" -> "+actual.getTopX()+" .. "+actual.getTopY());
					motionsSprite.add(actual);
				}
				actual = null;
				previous = null;
			}
			UniqueSpriteSheet css = null;
			String fileImage = null;
			PawnSheetKey pss = null;
			for(int i = 1; i < 5; i++)
			{
				css = new UniqueSpriteSheet();
				for (Sprite sprite : motionsSprite) 
				{
					css.addFrame(sprite);
				}

				String view = null;
				switch (i) 
				{
				case 1:
					view = PawnSheetKey.FRAME_POINT_YOUR_FRONT;
					break;
				case 2:
					view = PawnSheetKey.FRAME_POINT_YOUR_BACK;
					break;
				case 3:
					view = PawnSheetKey.FRAME_POINT_ENEMY_FRONT;
					break;
				default:
					view = PawnSheetKey.FRAME_POINT_ENEMY_BACK;
					break;
				}
				fileImage = (String) ((JSONObject) jsonResult.get(FILES)).get(view);
//				System.out.println("carico img "+pathFolder+fileImage);
				pss = (PawnSheetKey) psk.getCopy();
				pss.setWhen(view);
//				psk.setWhen(view);
//				css.setImage(ImageIO.read(new FileInputStream(pathFolder+File.separator+fileImage)));
				css.setImage(ImageIO.read(new FileInputStream(pathFolder+fileImage)));
				cache.add(pss,css);
//				cache.add(psk, css);
			}
	}

	/** */
	public UniqueSpriteSheet buildAvatarSprites(JSONObject jsonObject, PawnSheetKey psk, JSONObject informations)
	{
		UniqueSpriteSheet avatarsSheet = new UniqueSpriteSheet();
	
		avatarsSheet.addFrame(this.buildSimpleSprite((JSONObject) informations.get(AvatarFrameKey.CLASSIC_AVATAR), AvatarFrameKey.CLASSIC_AVATAR));
		avatarsSheet.addFrame(this.buildSimpleSprite((JSONObject) informations.get(AvatarFrameKey.LONG_AVATAR), AvatarFrameKey.LONG_AVATAR));
		avatarsSheet.addFrame(this.buildSimpleSprite((JSONObject) informations.get(AvatarFrameKey.MINI_AVATAR), AvatarFrameKey.MINI_AVATAR));
		avatarsSheet.addFrame(this.buildSimpleSprite((JSONObject) informations.get(AvatarFrameKey.PUPPET_MAP), AvatarFrameKey.PUPPET_MAP));
		
		return avatarsSheet;
	}
	
	/** */
	private Sprite buildSimpleSprite(final JSONObject jsonObject, final String name)
	{
		final String ROW = "row", 
				COLUMN = "column", 
				WIDTH = "width", 
				HEIGHT = "height";
		
		Sprite sprite = new Sprite();
		
		sprite.setFrameName(name);
		sprite.setTopX((int)((long)jsonObject.get(ROW)));
		sprite.setTopY((int)((long)jsonObject.get(COLUMN)));
		sprite.setWidth((int)((long)jsonObject.get(WIDTH)));
		sprite.setHeight((int)((long)jsonObject.get(HEIGHT)));
		
		return sprite;
	}
}
